
/* ===== pfod Command for Led Control ====
{.<w><+5><b>Using Ethernet Shield to turn D3 on and off|A~<+4><b>Pin D3 is
`0~~Low\High}
 */
// Using Arduino Ethernet Shield and SPI for send and receive
// With 128bit security, password is 1234  change this to your own with more hex digits
// Password upto 32 hex digits 0..9 A..F
// See parser.connect(.. ) for where to set the password

// You need to modify the MAC address, IP and port settings below 
// to match your shields MAC address and your network settings 

/* 
 * (c)2014-2015 Forward Computing and Control Pty. Ltd.
 * NSW Australia, www.forward.com.au
 * This generated code may be freely used for both private and commerical use
 */
// NOTE cannot use pin 13 for led as ethernet shield uses it
// Use D3 for output
#include <SPI.h>
#include <Ethernet.h>
// Download library from http://www.forward.com.au/pfod/pfodParserLibraries/index.html
#include <EEPROM.h> 
#include <pfodSecurity.h>
pfodSecurity parser; // create a parser to handle the pfod messages

// Enter a MAC address and IP address for your controller below.
// The IP addresses will be dependent on your local network.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 1, 1, 100);
const int portNo = 4989;
IPAddress gateway(10, 1, 1, 1);
IPAddress subnet(255, 255, 255, 0);

EthernetServer server(portNo);
EthernetClient client;
boolean alreadyConnected = false; // whether or not the client was connected previously

// give the board pins names, if you change the pin number here you will change the pin controlled
int cmd_A_pin = 3; // name the output pin for 'Pin D3 is '

// the setup routine runs once on reset:
void setup() {
  Serial.begin(9600);
  for (int i = 3; i > 0; i--) {
    // wait a few secs to see if we are being programmed
    delay(1000);
  }
  //pinMode(cmd_A_pin, INPUT_PULLUP);
  pinMode(cmd_A_pin, OUTPUT); // output for 'Pin D3 is ' is initially LOW, uncomment line above if you want it initially HIGH
  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);
  // start listening for clients
  server.begin();
  // initialize client
  client = server.available(); // evaluates to false if no connection

  // <<<<<<<<< Your extra setup code goes here
}

// the loop routine runs over and over again forever:
void loop() {
  if (!client) { // see if a client is available
    client = server.available(); // evaluates to false if no connection
  } else {
    // have client
    if (!client.connected()) {
      if (alreadyConnected) {
      // client closed so clean up
      Serial.println(F("Client closed, cleaning up"));
      closeConnection(parser.getPfodAppStream());
      }
    } else {
      // have connected client
      if (!alreadyConnected) {
        Serial.println(F("We have a new client"));
// Password set here in the connect method call, uses 19 bytes of EEPROM starting from 0        
        parser.connect(&client, F("1234")); // sets password and new io stream to read from and write to
//        int  eepromStartingAddress = 20;  // Or use these lines to specify the eeprom starting address
//        parser.connect(&client, F("1234"),  eepromStartingAddress); 
        alreadyConnected = true;
      }

      byte cmd = parser.parse(); // pass it to the parser
      // parser returns non-zero when a pfod command is fully parsed
      if (cmd != 0) { // have parsed a complete msg { to }
        byte* pfodFirstArg = parser.getFirstArg(); // may point to \0 if no arguments in this msg.
        long pfodLongRtn; // used for parsing long return arguments, if any
        if ('.' == cmd) {
          // pfodApp has connected and sent {.} , it is asking for the main menu
          // send back the menu designed
          sendMainMenu();

        // now handle commands returned from button/sliders
        } else if('A'==cmd) { // user moved slider -- 'Pin D3 is '
          // set output based on slider 0 == LOW, 1 == HIGH
          parser.parseLong(pfodFirstArg,&pfodLongRtn); // parse first arg as a long
          digitalWrite(cmd_A_pin,pfodLongRtn); // set output
          sendMainMenuUpdate(); // always send back a pfod msg otherwise pfodApp will disconnect.

        } else if ('!' == cmd) {
          // CloseConnection command
          closeConnection(parser.getPfodAppStream());
        } else {
          // unknown command
          parser.print(F("{}")); // always send back a pfod msg otherwise pfodApp will disconnect.
        }
      }
    }
  }
  
  //  <<<<<<<<<<<  Your other loop() code goes here 
  
}

void closeConnection(Stream *io) {
  // add any special code here to force connection to be dropped
  Serial.println(F("closeConnection"));
  parser.closeConnection(); // nulls io stream
  alreadyConnected = false;
  if (!client) {
    return;
  } // else
  client.stop();
  client = server.available(); // evaluates to false if no connection
}

void sendMainMenu() {
  parser.print(F("{.")); // start a Menu screen pfod message
  send_menuContents(); // send the menu contents
  parser.print(F("}")); // close pfod message
}

void sendMainMenuUpdate() {
  parser.print(F("{:")); // start an Update Menu pfod message
  send_menuContents(); // send the menu contents
  parser.print(F("}")); // close pfod message
}

// modify this method if you need to update the menu to reflect state changes
void send_menuContents() {
  // send menu prompt
  parser.print(F("<w><+5><b>Using Ethernet Shield to turn D3 on and off"));
  // send menu items
  parser.print(F("|A~<+4><b>Pin D3 is\n`"));
  parser.print(digitalRead(cmd_A_pin)); // read current output state 0 Low or 1 High
  parser.print(F("~~Low\\High")); // Note the \\ inside the "'s to send \ 
  // ============ end of menu item ===========
}

